package com.funtl.framework.java.util.common;

import java.text.ParseException;
import java.text.SimpleDateFormat;
import java.util.Calendar;
import java.util.Date;
import java.util.GregorianCalendar;
import java.util.TimeZone;
import java.util.Vector;

import com.funtl.framework.java.util.exception.UtilException;

/**
 * 通用日期工具
 * @author lwm
 *
 */
public class CommonDate {
	public static final int SECOND = 0;
	public static final int MINUTE = 1;
	public static final int HOUR = 2;
	public static final int DAY = 3;
	
	/**
	 * 获取年
	 * @return
	 */
	public static int getYear() {
		Calendar cal = Calendar.getInstance();
		return cal.get(Calendar.YEAR);
	}
	
	/**
	 * 获取月
	 * @return
	 */
	public static int getMonth() {
		Calendar cal = Calendar.getInstance();
		return cal.get(Calendar.MONTH) + 1;
	}
	
	/**
	 * 获取日
	 * @return
	 */
	public static int getDay() {
		Calendar cal = Calendar.getInstance();
		return cal.get(Calendar.DATE);
	}
	
	/**
	 * 获取当前日期时间
	 * @return
	 */
	public static String getDate() {
		SimpleDateFormat format = new SimpleDateFormat("yyyy-MM-dd");
		return format.format(new Date());
	}
	
	/**
	 * 获取当前日期时间
	 * @return
	 */
	public static String getDateTime() {
		SimpleDateFormat format = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");
		return format.format(new Date());
	}
	
	/**
	 * 获取当前自定义格式日期
	 * @return
	 */
	public static String getDateTimeCustom(String formatter) {
		SimpleDateFormat format = new SimpleDateFormat(formatter);
		return format.format(new Date());
	}
	
	/**
	 * 根据某个时间点获取相差分钟级的时间点
	 * @param pointTime 已知的时间点
	 * @param time 相差的时间（以分钟为单位）
	 * @return
	 * @throws UtilException
	 */
	@SuppressWarnings("static-access")
	public static String getDateTimeMinute(String pointTime, int time) throws UtilException {
		SimpleDateFormat sdf = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");
		String setlDate = null;
		Calendar calendar = Calendar.getInstance();
		try {
			calendar.setTime(sdf.parse(pointTime));
			calendar.add(calendar.MINUTE, time);
			setlDate = sdf.format(calendar.getTime());
			return setlDate;
		} catch (ParseException e) {
			throw new UtilException("getPointDate", e);
		}
	}
	
	/**
	 * 根据某个时间点获取相差秒级的时间点
	 * @param pointTime 已知的时间点
	 * @param time 相差的时间（以秒为单位）
	 * @return
	 * @throws UtilException
	 */
	@SuppressWarnings("static-access")
	public static String getDateTimeSecond(String pointTime, int time) throws UtilException {
		SimpleDateFormat sdf = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");
		String setlDate = null;
		Calendar calendar = Calendar.getInstance();
		try {
			calendar.setTime(sdf.parse(pointTime));
			calendar.add(calendar.SECOND, time);
			setlDate = sdf.format(calendar.getTime());
			return setlDate;
		} catch (ParseException e) {
			throw new UtilException("getPointDate", e);
		}
	}
	
	/**
	 * 获取时间的相差数
	 * @param begintime
	 * @param endtime
	 * @param type 类型常量
	 * 0 - 分钟
	 * 1 - 小时
	 * 2 - 天
	 * @return
	 * @throws UtilException
	 */
	public static int getDateTimeDifference(String begintime, String endtime, int type) throws UtilException {
		try {
			SimpleDateFormat inputFormat = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");
			long startT = inputFormat.parse(begintime).getTime();
			long endT = inputFormat.parse(endtime).getTime();
			
			long secd = (endT - startT) / (1000); // 共计秒数
			int mint = (int) secd / 60; // 共计分钟数
			int hor = (int) secd / 3600; // 共计小时数
			int day = (int) hor / 24; // 共计天数
			
			switch (type) {
			case 0:
				return (int) secd;
			case 1:
				return mint;
			case 2:
				return hor;
			case 3:
				return day;
			default:
				return 0;
			}
		} catch (ParseException e) {
			throw new UtilException("getDifferenceTime", e);
		}
	}
	
	/**
	 * 日期比较 
	 * @param date1
	 * @param date2
	 * 0 - date1 = date2 等于
	 * 1 - date1 > date2 大于
	 * -1 - date1 < date2 小于
	 * @return
	 */
	public static int getDateTimeCompare(String date1, String date2) {
		SimpleDateFormat format = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");
		try {
			Date d1 = format.parse(date1);
			Date d2 = format.parse(date2);
			int result = d1.compareTo(d2);
			return result;
		} catch (ParseException e) {
			throw new UtilException("getPointDate", e);
		}
	}
	
	/**
	 * 从一个样式转换到另一个样式
	 * @param date 字符串日期形式
	 * @param style1 需要转换的样式 如：yyyy-MM-dd HH:mm:ss
	 * @param style2 当前样式 如：yyMMddHHmmss
	 * @return
	 */
	public static String getDateTimeFormat(String date, String style1, String style2) {
		try {
			SimpleDateFormat format1 = new SimpleDateFormat(style1);
			SimpleDateFormat format2 = new SimpleDateFormat(style2);
			return format1.format(format2.parse(date));
		} catch (ParseException e) {
			throw new UtilException("formatDate", e);
		}
	}
	
	/**
	 * 获取当前日期对应的星期数. <br>
	 * 1=星期天,2=星期一,3=星期二,4=星期三,5=星期四,6=星期五,7=星期六
	 * 
	 * @return 当前日期对应的星期数
	 */
	public static int getDayOfWeek() {
		GregorianCalendar g = new GregorianCalendar();
		int ret = g.get(java.util.Calendar.DAY_OF_WEEK);
		g = null;
		return ret;
	}
	
	/**
	 * 获取所有的时区编号. <br>
	 * 排序规则:按照ASCII字符的正序进行排序. <br>
	 * 排序时候忽略字符大小写.
	 * 
	 * @return 所有的时区编号(时区编号已经按照字符[忽略大小写]排序).
	 */
	@SuppressWarnings({ "rawtypes", "unchecked" })
	public static String[] getAllTimeZoneIds() {
		Vector v = new Vector();
		String[] ids = TimeZone.getAvailableIDs();
		for (int i = 0; i < ids.length; i++) {
			v.add(ids[i]);
		}
		java.util.Collections.sort(v, String.CASE_INSENSITIVE_ORDER);
		v.copyInto(ids);
		v = null;
		return ids;
	}
	
	/**
	 * 获取系统当前默认时区与UTC的时间差.(单位:毫秒)
	 * 
	 * @return 系统当前默认时区与UTC的时间差.(单位:毫秒)
	 */
	public static int getDefaultTimeZoneRawOffset() {
		return TimeZone.getDefault().getRawOffset();
	}
	
	/**
	 * 获取指定时区与UTC的时间差.(单位:毫秒)
	 * 
	 * @param timeZoneId
	 *            时区Id
	 * @return 指定时区与UTC的时间差.(单位:毫秒)
	 */
	public static int getTimeZoneRawOffset(String timeZoneId) {
		return TimeZone.getTimeZone(timeZoneId).getRawOffset();
	}
	
	/**
	 * 获取系统当前默认时区与指定时区的时间差.(单位:毫秒)
	 * 
	 * @param timeZoneId
	 *            时区Id
	 * @return 系统当前默认时区与指定时区的时间差.(单位:毫秒)
	 */
	public static int getDiffTimeZoneRawOffset(String timeZoneId) {
		return TimeZone.getDefault().getRawOffset()
				- TimeZone.getTimeZone(timeZoneId).getRawOffset();
	}
	
	/**
	 * 转换时间时区
	 * @param convertString 需要转的时间字符串
	 * @param format 格式话字符串 例如d-MMM-yyyy HH:mm (z)
	 * @param sourceTimeZone 源时间时区
	 * @param targetTimeZone 目标时间时区
	 * @return
	 * @throws ParseException
	 */
	public static String getConverDateGMT(String convertString, String format, String sourceTimeZone, String targetTimeZone) throws ParseException {
		Date date = null;
		SimpleDateFormat sdf = new SimpleDateFormat(format);
		
		// 获取传入的时间值
		Long time = new Date(sdf.parse(convertString).getTime()).getTime();
		
		// 获取源时区时间相对的GMT时间
		Long sourceRelativelyGMT = time - TimeZone.getTimeZone(sourceTimeZone).getRawOffset();
		
		// GMT时间+目标时间时区的偏移量获取目标时间
		Long targetTime = sourceRelativelyGMT + TimeZone.getTimeZone(targetTimeZone).getRawOffset();
		
		date = new Date(targetTime);
		return sdf.format(date);
	}
	
	/**
	 * 给定一个日期型字符串，返回加减n天后的日期型字符串
	 * @param basicDate yyyy-MM-dd
	 * @param n
	 * @return
	 */
	public static String getDaysAfterOneDateString(String basicDate, int n) {
		SimpleDateFormat df = new SimpleDateFormat("yyyy-MM-dd");
		Date tmpDate = null;
		try {
			tmpDate = df.parse(basicDate);
		} catch (Exception e) {
			// 日期型字符串格式错误
		}
		long nDay = (tmpDate.getTime() / (24 * 60 * 60 * 1000) + 1 + n)
				* (24 * 60 * 60 * 1000);
		tmpDate.setTime(nDay);

		return df.format(tmpDate);
	}
	
	/**
	 * 得到本月的第一天
	 * 
	 * @return
	 */
	public static String getMonthFirstDay() {
		SimpleDateFormat format = new SimpleDateFormat("yyyy-MM-dd");
		Calendar calendar = Calendar.getInstance();
		calendar.set(Calendar.DAY_OF_MONTH,
				calendar.getActualMinimum(Calendar.DAY_OF_MONTH));
		return format.format(calendar.getTime());
	}

	/**
	 * 得到本月的最后一天
	 * 
	 * @return
	 */
	public static String getMonthLastDay() {
		SimpleDateFormat format = new SimpleDateFormat("yyyy-MM-dd");
		Calendar calendar = Calendar.getInstance();
		calendar.set(Calendar.DAY_OF_MONTH,
				calendar.getActualMaximum(Calendar.DAY_OF_MONTH));
		return format.format(calendar.getTime());
	}
	
	/**
	 * 得到某年某月的第一天
	 * 
	 * @param year
	 * @param month
	 * @return
	 */
	public static String getFirstDayOfMonth(int year, int month) {
		Calendar cal = Calendar.getInstance();
		cal.set(Calendar.YEAR, year);
		cal.set(Calendar.MONTH, month - 1);
		cal.set(Calendar.DAY_OF_MONTH, cal.getMinimum(Calendar.DATE));
		return new SimpleDateFormat("yyyy-MM-dd").format(cal.getTime());
	}
	
	/**
	 * 得到某年某月的最后一天
	 * 
	 * @param year
	 * @param month
	 * @return
	 */
	public static String getLastDayOfMonth(int year, int month) {
		Calendar cal = Calendar.getInstance();
		cal.set(Calendar.YEAR, year);
		cal.set(Calendar.MONTH, month - 1);
		cal.set(Calendar.DAY_OF_MONTH, 1);
		int value = cal.getActualMaximum(Calendar.DAY_OF_MONTH);
		cal.set(Calendar.DAY_OF_MONTH, value);
		return new SimpleDateFormat("yyyy-MM-dd").format(cal.getTime());
	}

	public static void main(String[] args) throws ParseException {
		//时区互转
		System.out.println(getConverDateGMT("2013-12-02 08:00:00", "yyyy-MM-dd HH:mm:ss", "PST", "GMT+8"));
		
		//日期加天(填负数为减)
		System.out.println(getDaysAfterOneDateString("2013-12-14", 2));
	}
}
